!> author: 左志华
!> date: 2022-07-19
!>
!> Command Line Interface <br>
!> 命令行界面：<br>
!> 1. 前处理：`to-sph pre --type:T 'lua'`；<br>
!> 2. 后处理：`to-sph post --type:T 'vtk'`
!> @note 命令行界面覆盖 TOML 文件中的配置，如果 TOML 文件和 CLI 中都没有配置，则使用默认配置（lua->h5part->?）。
module sph_command_line

    use M_CLI2, only: set_args, get_subcommand, sget, lget
    use seakeeping_string, only: newline
    use seakeeping_error_handling, only: fatal_error
    implicit none
    private

    public :: get_cmd_settings, cmd_settings_t, &
              pre_settings_t, post_settings_t

    !> CLI class <br>
    !> CLI 抽象类
    type, abstract :: cmd_settings_t
        character(:), allocatable :: working_dir    !! Working directory <br>
                                                    !! 工作目录
        character(:), allocatable :: type           !! Pre-processing type <br>
                                                    !! 前处理类型
        logical :: skip = .false.                   !! Skip pre-processing asking <br>
                                                    !! 跳过前处理询问
    end type cmd_settings_t

    !> Pre-processing class <br>
    !> 前处理类
    type, extends(cmd_settings_t) :: pre_settings_t
    end type pre_settings_t

    !> Post-processing class <br>
    !> 后处理类
    type, extends(cmd_settings_t) :: post_settings_t
    end type post_settings_t

contains

    !> Get command line settings <br>
    !> 获取命令行参数
    subroutine get_cmd_settings(cmd_settings)
        class(cmd_settings_t), allocatable, intent(out) :: cmd_settings     !! Command line settings <br>
                                                                            !! 命令行参数
        character(*), parameter :: version_text(*) = &
            &[character(100) :: &
            "@(#)程序  ：to-sph(1) >", &
            "@(#)描述  ：sph / ti-sph 项目前后处理工具 >", &
            "@(#)版本  ：0.4.1, alpha (构建于 2022-10-23) >", &
            "@(#)作者  ：左志华 >", &
            "@(#)许可证：MIT >", &
            "@(#)源仓库：https://gitee.com/fortran-sph/to-sph >"]
        character(*), parameter :: help_to_sph(*) = &
            &[character(100) :: &
            'NAME', &
            '   to-sph(1) - sph / ti-sph 项目前后处理工具'//newline, &
            'SYNOPSIS', &
            '   to-sph SUBCOMMAND [SUBCOMMAND_OPTIONS]', &
            '   to-sph --help|--version'//newline, &
            'DESCRIPTION', &
            '   to-sph(1) 是一个 sph / ti-sph 项目前后处理工具。'//newline, &
            'SUBCOMMANDS', &
            '   有效的 to-sph(1) 的子命令如下：', &
            '   + pre   前处理', &
            '   + post  后处理', &
            '   它们的语法是：', &
            '       to-sph pre  [--type:T TYPE] [--directory:C DIR] [--skip]', &
            '       to-sph post [--type:T TYPE] [--directory:C DIR]'//newline, &
            '对所有子命令都有效的选项如下：', &
            '   --help      显示此帮助信息', &
            '   --version   显示版本信息'//newline, &
            'EXAMPLES', &
            '   命令示例：', &
            '       to-sph pre  --type:T "lua" --directory "."', &
            '       to-sph post -T "vtk" -C "example"'//newline &
            ]
        character(*), parameter :: help_pre(*) = &
            &[character(100) :: &
            "NAME", &
            "   pre(1) - to-sph(1) 子命令：前处理"//newline, &
            "SYNOPSIS", &
            "   to-sph pre [--type:T TYPE] [--directory:C DIR] [--skip]", &
            "   to-sph pre --help|--version"//newline, &
            "DESCRIPTION", &
            '   "to-sph pre"命令', &
            '       + 将初始化粒子信息转化为 .h5part 文件'//newline, &
            '   项目文件被假定放置在 DIR 目录中，如果没有指定，则使用当前目录：', &
            '       + pif.lua    to-sph 生成粒子信息 Lua 脚本', &
            '       + pif.h5part sph / ti-sph 可读粒子信息文件'//newline, &
            'OPTIONS', &
            '   --type:T TYPE       前处理类型，默认值："lua"', &
            '   --directory:C DIR   工作目录，默认值：当前目录', &
            '   --skip              跳过前处理询问', &
            '   --help              显示帮助信息', &
            '   --version           显示版本信息'//newline &
            ]
        character(*), parameter :: help_post(*) = &
            &[character(100) :: &
            "NAME", &
            "   post(1) - to-sph(1) 子命令：后处理 (@note 未实现)"//newline, &
            "SYNOPSIS", &
            "   to-sph post [--type:T TYPE] [--directory:C DIR]", &
            "   to-sph post --help|--version"//newline, &
            "DESCRIPTION", &
            '   "to-sph post"命令', &
            '       + 将 .h5part 文件转化为 .vtk 文件'//newline, &
            '   项目文件被假定放置在 DIR 目录中，如果没有指定，则使用当前目录：', &
            '       + pif.h5part sph / ti-sph 可读粒子信息文件', &
            '       + pif.h5part H5Part 文件', &
            '       + pif.vtk    VTK 文件'//newline, &
            'OPTIONS', &
            '   --type:T TYPE       后处理类型，无默认值, 可选值："vtk"', &
            '   --directory:C DIR   工作目录，默认值：当前目录', &
            '   --help              显示帮助信息', &
            '   --version           显示版本信息'//newline &
            ]

        character(:), allocatable :: subcmd

        subcmd = get_subcommand()

        select case (subcmd)
        case ('pre')
            call set_args("--directory:C '.'&
            & --type:T 'lua'&
            & --skip F&
            & --", help_pre, version_text)
            allocate (pre_settings_t :: cmd_settings)

        case ('post')
            call set_args("--directory:C '.'&
            & --type:T 'vtk'&
            & --skip F&
            & --", help_post, version_text)
            allocate (post_settings_t :: cmd_settings)

        case default
            call set_args("", help_to_sph, version_text)
            if (subcmd == "") then
                print '(a)', help_to_sph
                stop
            else
                call fatal_error("未知子命令："//subcmd)
            end if

        end select

        if (allocated(cmd_settings)) then
            cmd_settings%working_dir = sget("directory")
            cmd_settings%type = sget("type")
            cmd_settings%skip = lget("skip")
        end if

    end subroutine get_cmd_settings

end module sph_command_line
